/*
 * Created on Jul 14, 2004
 *
 * To change the template for this generated file go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
package com.inspectortime.common;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.util.StringUtils;

import com.inspectortime.repository.PersistentEntityServiceAggregator;

/**
 * @author wko
 */
@MappedSuperclass
public abstract class PersistentEntityBase extends PersistentObjectBase {

	private static Log log = LogFactory.getLog(PersistentEntityBase.class);

	private Serializable id;

	private static PersistentEntityServiceAggregator services;

	@Id
	@Type(type="org.hibernate.type.StringType")
	@GeneratedValue(generator = "system-uuid")
	@GenericGenerator(name = "system-uuid", strategy = "uuid")
	@Column( length = 32 )
	public Serializable getId() {
		return id;
	}

	@Transient
	protected static PersistentEntityServiceAggregator getServices() {
		return services;
	}
	
	/**
	 * Saves the entity using the injected sessionFactory.
	 * 
	 * Note that we are using SessionFactoryUtils.getSession(..) to retrieve the
	 * hibernate session bound to threadlocal instead of relying on Spring's
	 * HibernateTemplate to do it. Either way probably works but using
	 * SessionFactoryUtils allows for greater control of session binding and
	 * release, which was found to be useful when setting up unit tests that
	 * include lazy loading of objects (in assert statements).
	 * @see http://today.java.net/pub/a/today/2005/10/11/testing-hibernate-mapping.html?page=2
	 * 
	 * @return
	 */
	public Serializable save() {
		Session session = SessionFactoryUtils.getSession(getServices().getSessionFactory(), true);
		if (!StringUtils.hasText((String) this.getId())) {
			this.setId(null);
			session.save(this);
		} else {
			
			// Only call explicit update if instanced is not known to the session (o/w it will be updated at flush time)
			if (!session.contains(this)) {
				session.update(this);
			}
		}
		
		// TODO: Move flush to the end of OpenSessionInView somehow
		session.flush(); //Need to manually flush, as we've removed AUTO_FLUSH from the OpenSessionInViewFilter
		return this.getId();
	}

	@SuppressWarnings("unused")
	private void setId(Serializable id) {
		this.id = id;
	}

	@Transient
	public static void setServices(PersistentEntityServiceAggregator s) {
		services = s;
	}

}